package com.zero.guava.samples.RateLimiter;


import com.google.common.util.concurrent.RateLimiter;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * RateLimiterTest类与Java api中的semaphore信号量比较类似,主要用于限制对资源并发访问的线程数，
 * RateLimiter类限制线程访问的时间,这就意味着可以限制每秒中线程访问资源的数量
 */
public class RateLimiterTest {

    private ExecutorService executor;

    @Before
    public void setUp(){
        executor = Executors.newCachedThreadPool();
    }

    @Test
    public void testRateLimiter(){
        //create(double permitsPerSecond):创建具有指定稳定吞吐量的RateLimiter类,传入允许每秒提交的任务数量.
        //create(double permitsPerSecond,long warmupPeriod, TimeUnit unit):创建具有指定稳定吞吐量的RateLimiter类,
        //传入允许每秒提交的任务数量和准备阶段的时间,在这段时间RateLimiter会有个缓冲,直到达到它的最大速率（只要有饱和的足够的请求）
        RateLimiter limiter = RateLimiter.create(4.0);

        //acquire():从这个ratelimiter获得一个许可,阻塞线程直到请求可以再授予许可
        //acquire(int permits):获取传入数量的许可,阻塞线程直到请求可以再授予许可
        limiter.acquire();
        executor.submit(new Callable<Object>() {

            @Override
            public Object call() throws Exception {
                return "Hello RateLimiter";
            }
        });

        //tryAcquire(long timeout, TimeUnit unit)：判断是否可以在指定的时间内从ratelimiter获得一个许可,
        // 或者在超时期间内未获得许可的话，立即返回false。
        //tryAcquire(int permits)：判断是否可以立即获取相应数量的许可。
        //tryAcquire():判断是否可以立即获取许可。
        //tryAcquire(int permits, long timeout, TimeUnit unit):判断是否可以在超时时间内获取相应数量的许可。
        if (limiter.tryAcquire()){
            //有资源访问的许可
            System.out.println("someThing");
        }else{
            //没有资源访问的许可
            System.out.println("anotherThing");
        }

    }
}
